package com.kinyx.framework.reflect;

import java.util.Date;
import java.util.List;

import javax.util.XArrayList;
import javax.util.XHashMap;

import org.junit.Assert;
import org.junit.Test;

import com.kinyx.framework.TypeConvert.TestVo;
import com.kinyx.framework.utils.KDateTimeUtils;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

public class KTypeConverter_Tester_convert {

	private void equal(final Object obj, final Class<?> clazz) {
		String excepted = String.valueOf(obj);
		switch (obj.getClass().getName()) {
			case "float":
			case "java.lang.Float":
			case "double":
			case "java.lang.Double":
				switch (clazz.getName()) {
					case "float":
					case "java.lang.Float":
					case "double":
					case "java.lang.Double":
						break;
					default :
						excepted = excepted.replaceAll(".0", "");
						break;

				}
				break;
			default :
				switch (clazz.getName()) {
					case "float":
					case "java.lang.Float":
					case "double":
					case "java.lang.Double":
						excepted += ".0";
						break;
					default :
						break;

				}
				break;
		}
		Assert.assertEquals(excepted, String.valueOf(KTypeConverter.convert(obj, clazz)));
	}

	@Test
	public void 默认值1() {
		Assert.assertTrue(KTypeConverter.convert(null, byte.class) == (byte) 0);
		Assert.assertTrue(KTypeConverter.convert(null, short.class) == (short) 0);
		Assert.assertTrue(KTypeConverter.convert(null, int.class) == 0);
		Assert.assertTrue(KTypeConverter.convert(null, long.class) == 0L);
		Assert.assertTrue(KTypeConverter.convert(null, float.class) == 0f);
		Assert.assertTrue(KTypeConverter.convert(null, double.class) == 0d);

		Assert.assertTrue(KTypeConverter.convert(null, char.class) == (char) 0);
		Assert.assertTrue(KTypeConverter.convert(null, boolean.class) == false);
	}

	@Test
	public void 默认值2() {
		Assert.assertNull(KTypeConverter.convert(null, Byte.class));
		Assert.assertNull(KTypeConverter.convert(null, Short.class));
		Assert.assertNull(KTypeConverter.convert(null, Integer.class));
		Assert.assertNull(KTypeConverter.convert(null, Long.class));
		Assert.assertNull(KTypeConverter.convert(null, Float.class));
		Assert.assertNull(KTypeConverter.convert(null, Double.class));

		Assert.assertNull(KTypeConverter.convert(null, Character.class));
		Assert.assertNull(KTypeConverter.convert(null, Boolean.class));
	}

	@Test
	public void 默认值3() {
		Assert.assertNull(KTypeConverter.convert(null, String.class));

		Assert.assertNull(KTypeConverter.convert(null, Date.class));
	}

	// 1.1、布尔型转布尔型
	@Test
	public void 布尔型转布尔型() {
		// boolean
		Assert.assertTrue(KTypeConverter.convert(true, Boolean.class));
		Assert.assertFalse(KTypeConverter.convert(false, Boolean.class));
	}

	// 1.2、字符型转布尔型
	@Test
	public void 字符型转布尔型() {
		// char
		Assert.assertTrue(KTypeConverter.convert((char) 1, Boolean.class));
		Assert.assertFalse(KTypeConverter.convert((char) 0, Boolean.class));
	}

	// 1.3、数字型转布尔型
	@Test
	public void 数字型转布尔型() {
		// byte
		Assert.assertTrue(KTypeConverter.convert((byte) 1, Boolean.class));
		Assert.assertFalse(KTypeConverter.convert((byte) 0, Boolean.class));

		// short
		Assert.assertTrue(KTypeConverter.convert((short) 1, Boolean.class));
		Assert.assertFalse(KTypeConverter.convert((short) 0, Boolean.class));

		// int
		Assert.assertTrue(KTypeConverter.convert(1, Boolean.class));
		Assert.assertFalse(KTypeConverter.convert(0, Boolean.class));

		// long
		Assert.assertTrue(KTypeConverter.convert(1L, Boolean.class));
		Assert.assertFalse(KTypeConverter.convert(0L, Boolean.class));

		// float
		Assert.assertTrue(KTypeConverter.convert(1f, Boolean.class));
		Assert.assertFalse(KTypeConverter.convert(0f, Boolean.class));

		// double
		Assert.assertTrue(KTypeConverter.convert(1d, Boolean.class));
		Assert.assertFalse(KTypeConverter.convert(0d, Boolean.class));
	}

	// 1.4、字符串型转布尔型
	@Test
	public void 字符串型转布尔型() {
		Assert.assertTrue(KTypeConverter.convert("1", Boolean.class));
		Assert.assertTrue(KTypeConverter.convert("true", Boolean.class));
		Assert.assertTrue(KTypeConverter.convert("T", Boolean.class));
		Assert.assertTrue(KTypeConverter.convert("YES", Boolean.class));
		Assert.assertTrue(KTypeConverter.convert("Y", Boolean.class));

		Assert.assertFalse(KTypeConverter.convert("", Boolean.class));
		Assert.assertFalse(KTypeConverter.convert("0", Boolean.class));
		Assert.assertFalse(KTypeConverter.convert("false", Boolean.class));
		Assert.assertFalse(KTypeConverter.convert("F", Boolean.class));
		Assert.assertFalse(KTypeConverter.convert("NO", Boolean.class));
		Assert.assertFalse(KTypeConverter.convert("N", Boolean.class));
	}

	// 1.5、布尔型转数字型
	@Test
	public void 布尔型转数字型() {
		Assert.assertTrue(KTypeConverter.convert(true, Byte.class) == (byte) 1);
		Assert.assertTrue(KTypeConverter.convert(true, Short.class) == (short) 1);
		Assert.assertTrue(KTypeConverter.convert(true, Integer.class) == 1);
		Assert.assertTrue(KTypeConverter.convert(true, Long.class) == 1L);
		Assert.assertTrue(KTypeConverter.convert(true, Float.class) == 1f);
		Assert.assertTrue(KTypeConverter.convert(true, Double.class) == 1d);

		Assert.assertTrue(KTypeConverter.convert(false, Byte.class) == (byte) 0);
		Assert.assertTrue(KTypeConverter.convert(false, Short.class) == (short) 0);
		Assert.assertTrue(KTypeConverter.convert(false, Integer.class) == 0);
		Assert.assertTrue(KTypeConverter.convert(false, Long.class) == 0L);
		Assert.assertTrue(KTypeConverter.convert(false, Float.class) == 0f);
		Assert.assertTrue(KTypeConverter.convert(false, Double.class) == 0d);
	}

	// 2.1、布尔型转字符型
	@Test
	public void 布尔型转字符型() {
		Assert.assertTrue(KTypeConverter.convert(true, Character.class) == (char) 1);
		Assert.assertTrue(KTypeConverter.convert(false, Character.class) == (char) 0);
	}

	// 2.2、字符型转字符型
	@Test
	public void 字符型转字符型() {
		Assert.assertTrue(KTypeConverter.convert((char) 1, Character.class) == (char) 1);
		Assert.assertTrue(KTypeConverter.convert((char) 0, Character.class) == (char) 0);
	}

	// 2.3、数字型转字符型
	@Test
	public void 数字型转字符型1() {
		Assert.assertTrue(KTypeConverter.convert((byte) 1, Character.class) == (char) 1);
		Assert.assertTrue(KTypeConverter.convert((short) 1, Character.class) == (char) 1);
		Assert.assertTrue(KTypeConverter.convert(1, Character.class) == (char) 1);
		Assert.assertTrue(KTypeConverter.convert(1L, Character.class) == (char) 1);
		Assert.assertTrue(KTypeConverter.convert(1f, Character.class) == (char) 1);
		Assert.assertTrue(KTypeConverter.convert(1d, Character.class) == (char) 1);
	}

	// 2.4、字符串型转字符型
	@Test
	public void 字符串型转字符型() {
		Assert.assertTrue(KTypeConverter.convert("", Character.class) == (char) 0);
		Assert.assertTrue(KTypeConverter.convert("1", Character.class) == "1".charAt(0));
	}

	// 2.5、字符型转数字型
	@Test
	public void 字符型转数字型() {
		Assert.assertTrue(KTypeConverter.convert((char) 1, Byte.class) == (byte) 1);
		Assert.assertTrue(KTypeConverter.convert((char) 1, Short.class) == (short) 1);
		Assert.assertTrue(KTypeConverter.convert((char) 1, Integer.class) == 1);
		Assert.assertTrue(KTypeConverter.convert((char) 1, Long.class) == 1L);
		Assert.assertTrue(KTypeConverter.convert((char) 1, Float.class) == 1f);
		Assert.assertTrue(KTypeConverter.convert((char) 1, Double.class) == 1d);

		Assert.assertTrue(KTypeConverter.convert((char) 0, Byte.class) == (byte) 0);
		Assert.assertTrue(KTypeConverter.convert((char) 0, Short.class) == (short) 0);
		Assert.assertTrue(KTypeConverter.convert((char) 0, Integer.class) == 0);
		Assert.assertTrue(KTypeConverter.convert((char) 0, Long.class) == 0L);
		Assert.assertTrue(KTypeConverter.convert((char) 0, Float.class) == 0f);
		Assert.assertTrue(KTypeConverter.convert((char) 0, Double.class) == 0d);
	}

	// 3、数字型互转
	@Test
	public void 数字型互转() {
		final List<Object> numbers = new XArrayList<>().xAdd((byte) 123).xAdd((short) 123).xAdd(123).xAdd(123L).xAdd(123f).xAdd(123d);
		final List<Object> numberTypes = new XArrayList<>()//
				.xAdd(Byte.class)//
				.xAdd(Short.class)//
				.xAdd(Integer.class)//
				.xAdd(Long.class)//
				.xAdd(Float.class)//
				.xAdd(Double.class)//
		;
		numbers.forEach(value -> { numberTypes.forEach(clazz -> { this.equal(value, (Class<?>) clazz); }); });
	}

	// 4.1、布尔型转字符串型
	@Test
	public void 布尔型转字符串型() {
		Assert.assertTrue(KTypeConverter.convert(true, String.class).equals("true"));
		Assert.assertTrue(KTypeConverter.convert(false, String.class).equals("false"));
	}

	// 4.2、字符型转字符串型
	@Test
	public void 字符型转字符串型() {
		Assert.assertTrue(KTypeConverter.convert((char) 0, String.class).equals(String.valueOf((char) 0)));
		Assert.assertTrue(KTypeConverter.convert((char) 1, String.class).equals(String.valueOf((char) 1)));
	}

	// 4.3、数字型转字符串型
	@Test
	public void 数字型转字符串型() {
		Assert.assertTrue(KTypeConverter.convert((byte) 1, String.class).equals("1"));
		Assert.assertTrue(KTypeConverter.convert((short) 1, String.class).equals("1"));
		Assert.assertTrue(KTypeConverter.convert(1, String.class).equals("1"));
		Assert.assertTrue(KTypeConverter.convert(1L, String.class).equals("1"));
		Assert.assertTrue(KTypeConverter.convert(1f, String.class).equals("1.0"));
		Assert.assertTrue(KTypeConverter.convert(1d, String.class).equals("1.0"));
	}

	// 4.4、字符串型转字符串型
	@Test
	public void 字符串型转字符串型() {
		Assert.assertTrue(KTypeConverter.convert("str", String.class).equals("str"));
	}

	// 4.5、字符串型转数字型
	@Test
	public void 字符串型转数字型() {
		Assert.assertTrue(KTypeConverter.convert("1", Byte.class) == (byte) 1);
		Assert.assertTrue(KTypeConverter.convert("1", Short.class) == (short) 1);
		Assert.assertTrue(KTypeConverter.convert("1", Integer.class) == 1);
		Assert.assertTrue(KTypeConverter.convert("1", Long.class) == 1L);
		Assert.assertTrue(KTypeConverter.convert("1", Float.class) == 1f);
		Assert.assertTrue(KTypeConverter.convert("1", Double.class) == 1d);
	}

	// 5、常用类型实现
	@Test
	public void 日期类型() {
		// 5.1、日期类型互转
		Assert.assertEquals(new Date(1), KTypeConverter.convert(new Date(1), Date.class));

		// 5.2、日期类型与Long互转
		Assert.assertEquals(1L, KTypeConverter.convert(1L, Date.class).getTime());
		Assert.assertEquals(new Date(1), new Date(KTypeConverter.convert(new Date(1), Long.class)));

		// 5.3、日期类型与字符串互转
		Assert.assertEquals("20180206000000000", KDateTimeUtils.toString(KTypeConverter.convert("20180206000000000", Date.class), null));
		Assert.assertEquals("20180206000000000", KTypeConverter.convert(KDateTimeUtils.toDate("20180206000000000", null), String.class));
	}

	@Test
	public void 自定义类型() {
		// 自定义类型转换器，按照规则实现。
		Assert.assertEquals("str", KTypeConverter.convert("str", TestVo.class).getStr());
	}

	@Test
	public void 动态增加转换方法() {
		// 动态增加转换方法
		Assert.assertThrows(Exception.class, () -> {// 这个时候还没有该转换器，所以会报错。
			try {
				KTypeConverter_Tester_convert.this.testDynamicAddConverter();
			} catch (final Exception e) {
				throw e;
			}
		});
		// 动态添加转换器
		KTypeConverter.addConverter(String.class, TestBean.class, source -> { return new TestBean(source); });
		// 这个时候就可以进行转换了
		this.testDynamicAddConverter();
	}

	private void testDynamicAddConverter() { Assert.assertEquals("str", KTypeConverter.convert("str", TestBean.class).getStr()); }

	@Getter
	@Setter
	@AllArgsConstructor
	public class TestBean {
		private String str;
	}

	@Test
	public void 集合转Bean() {
		Assert.assertEquals("str", KTypeConverter.convert(new XHashMap<String, String>().xPut("str", "str"), TestVo.class).getStr());
	}

}
